#include "sshconnection.h"

#include <QDebug>

// #include <chrono>
// #include <thread>

namespace Ssh {
    constexpr uint M_SECOND = 100000;

SshConnection::SshConnection(SshLoginKeys loginKeys, QObject* parent)
    : QObject(parent)
    , mLoginKeys(std::move(loginKeys))
    {
    }

    SshConnection::~SshConnection()
    {
    }


    void SshConnection::ConnectSsh()
    {
        auto sshSession = SshSession(mLoginKeys.user, mLoginKeys.host, mLoginKeys.port, mLoginKeys.password);

        if (!sshSession.IsNull() && !sshSession.connect()) {
            emit SshStandardError(sshSession.GetError());
            return;
        }

        auto sshChannel = SshChannel(sshSession.CreateChannel());
        if (sshChannel.IsNull()) {
            emit SshStandardError(sshSession.GetError());
            return;
        }

        if (!sshChannel.IsOpen() && !sshChannel.Open()) {
            emit SshStandardError(sshSession.GetError());
            return;
        }

        if (!sshChannel.RunInteractiveShell(40, 20)) {
            emit SshStandardError(sshSession.GetError());
            return;
        } else {
            QByteArray buffer;
            buffer.resize(1024);
            int length = 0;
            while ((length = sshChannel.Read(buffer.data(), buffer.size(), 100)) > 0) {
                buffer.resize(length);
                emit SshStandardOutput(buffer.toStdString());
                buffer.resize(1024);
            }
        }

        emit SshConnected();
        {
            std::scoped_lock lock(mMutex);
            mIsConnect = true;
        }
        while (sshChannel.IsOpen() && mIsConnect) {
            auto command = const_cast<char*>(mCommand.c_str());
            if (!mCommand.empty() && sshChannel.Write(command, strlen(command))) {
                mIsExecing = true;
                emit SshExecStarted();
                mCommand.clear();
            }
            QByteArray buffer;
            buffer.resize(1024);
            int length = 0;
            while (mIsExecing && (length = sshChannel.Read(buffer.data(), buffer.size(), 100)) > 0) {
                buffer.resize(length);
                emit SshStandardOutput(buffer.toStdString());
                buffer.resize(1024);
            }
            if (mIsExecing) {
                emit SshExecFinished();
                mIsExecing = false;
            }
            usleep(M_SECOND); // 避免高 CPU 使用率
            // using namespace std::chrono_literals;
            // std::this_thread::sleep_for(100ms);
        }
        sshChannel.Close();
    }

    void SshConnection::DisconnectSsh()
    {
        std::scoped_lock lock(mMutex);
        qDebug() << "DisconnectSsh";
        mIsConnect = false;
    }

    void SshConnection::SendCommand(const std::string& command)
    {
        mCommand = command;
        qDebug() << mCommand;
    }
}
